﻿////Copyright 2012 - Jonathan Allen

//using System;
//using System.Collections.Generic;
//using System.Diagnostics.Contracts;
//using System.Globalization;
//using System.Linq;
//using System.Diagnostics.CodeAnalysis;


//namespace Granite.Time
//{
//    /// <summary>
//    /// This represents a date without a time component.
//    /// </summary>
//    public struct DateOnly
//    {
//        /// <summary>
//        /// This is always stored as UTC
//        /// </summary>
//        readonly DateTime m_UnderlyingValue;

//        /// <summary>
//        /// 
//        /// </summary>
//        public static readonly DateTime MaxValue = DateTime.MaxValue.Date;
//        /// <summary>
//        /// 
//        /// </summary>
//        public static readonly DateTime MinValue = DateTime.MinValue.Date;

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="date"></param>
//        public DateOnly(DateTime date)
//            : this(date.Year, date.Month, date.Day)
//        {
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="year"></param>
//        /// <param name="month"></param>
//        /// <param name="day"></param>
//        public DateOnly(int year, int month, int day)
//        {
//            if (year < 1)
//                throw ExceptionUtilities.ArgumentOutOfRangeException("year", year, "year must be >= 1");
//            if (year > 9999)
//                throw ExceptionUtilities.ArgumentOutOfRangeException("year", year, "year must be <= 9999");
//            if (month < 1)
//                throw ExceptionUtilities.ArgumentOutOfRangeException("month", month, "month must be >= 1");
//            if (month > 12)
//                throw ExceptionUtilities.ArgumentOutOfRangeException("month", month, "month must be < 12");
//            if (day < 1)
//                throw ExceptionUtilities.ArgumentOutOfRangeException("day", day, "day must be >= 1");
//            Contract.EndContractBlock();

//            m_UnderlyingValue = new DateTime(year, month, day);
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="year"></param>
//        /// <param name="month"></param>
//        /// <param name="day"></param>
//        /// <param name="calendar"></param>
//        public DateOnly(int year, int month, int day, Calendar calendar)
//        {
//            m_UnderlyingValue = new DateTime(year, month, day, 0, 0, 0, 0, calendar, DateTimeKind.Utc);
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        public int Year
//        {
//            get { return m_UnderlyingValue.Year; }
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        public int Month
//        {
//            get { return m_UnderlyingValue.Month; }
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        public int Day
//        {
//            get { return m_UnderlyingValue.Day; }
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        public long Ticks
//        {
//            get { return m_UnderlyingValue.Ticks; }
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="d1"></param>
//        /// <param name="d2"></param>
//        /// <returns></returns>
//        public static TimeSpan operator -(DateOnly d1, DateOnly d2)
//        {
//            return d1.m_UnderlyingValue - d2.m_UnderlyingValue;
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="d2"></param>
//        /// <returns></returns>
//        public TimeSpan Subtract(DateOnly d2)
//        {
//            return this.m_UnderlyingValue - d2.m_UnderlyingValue;
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="d1"></param>
//        /// <param name="d2"></param>
//        /// <returns></returns>
//        public static bool operator !=(DateOnly d1, DateOnly d2)
//        {
//            return d1.m_UnderlyingValue != d2.m_UnderlyingValue;

//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="t1"></param>
//        /// <param name="t2"></param>
//        /// <returns></returns>
//        public static bool operator <(DateOnly t1, DateOnly t2)
//        {
//            return t1.m_UnderlyingValue < t2.m_UnderlyingValue;
//        }
	
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="t1"></param>
//        /// <param name="t2"></param>
//        /// <returns></returns>
//        public static bool operator <=(DateOnly t1, DateOnly t2)
//        {
//            return t1.m_UnderlyingValue <= t2.m_UnderlyingValue;
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="d1"></param>
//        /// <param name="d2"></param>
//        /// <returns></returns>
//        public static bool operator ==(DateOnly d1, DateOnly d2)
//        {
//            return d1.m_UnderlyingValue == d2.m_UnderlyingValue;
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="t1"></param>
//        /// <param name="t2"></param>
//        /// <returns></returns>
//        public static bool operator >(DateOnly t1, DateOnly t2)
//        {
//            return t1.m_UnderlyingValue > t2.m_UnderlyingValue;
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="t1"></param>
//        /// <param name="t2"></param>
//        /// <returns></returns>
//        public static bool operator >=(DateOnly t1, DateOnly t2)
//        {
//            return t1.m_UnderlyingValue >= t2.m_UnderlyingValue;
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="days"></param>
//        /// <returns></returns>
//        public DateOnly AddDays(int days)
//        {
//            return new DateOnly(m_UnderlyingValue.AddDays(days));
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="months"></param>
//        /// <returns></returns>
//        public DateOnly AddMonths(int months)
//        {
//            return new DateOnly(m_UnderlyingValue.AddMonths(months));
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="years"></param>
//        /// <returns></returns>
//        public DateOnly AddYears(int years)
//        {
//            return new DateOnly(m_UnderlyingValue.AddYears(years));
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="t1"></param>
//        /// <param name="t2"></param>
//        /// <returns></returns>
//        public static int Compare(DateOnly t1, DateOnly t2)
//        {
//            return DateTime.Compare(t1.m_UnderlyingValue, t2.m_UnderlyingValue);
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="value"></param>
//        /// <returns></returns>
//        public int CompareTo(DateOnly value)
//        {
//            return m_UnderlyingValue.CompareTo(value.m_UnderlyingValue);
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="value"></param>
//        /// <returns></returns>
//        public int CompareTo(object value)
//        {
//            var t2 = (DateOnly)value;
//            return CompareTo(t2);
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="value"></param>
//        /// <returns></returns>
//        public bool Equals(DateOnly value)
//        {
//            return m_UnderlyingValue.Equals(value.m_UnderlyingValue);
//        }

//        /// <summary>
//        /// Determines whether the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />.
//        /// </summary>
//        /// <returns>
//        /// true if the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />; otherwise, false.
//        /// </returns>
//        /// <param name="obj">
//        /// The <see cref="T:System.Object" /> to compare with the current <see cref="T:System.Object" />. 
//        /// </param>
//        /// <filterpriority>2</filterpriority>
//        public override bool Equals(object obj)
//        {
//            if (obj == null)
//                return false;
//            if (!(obj is DateOnly))
//                return false;
//            var t2 = (DateOnly)obj;
//            return m_UnderlyingValue.Equals(t2.m_UnderlyingValue);
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="t1"></param>
//        /// <param name="t2"></param>
//        /// <returns></returns>
//        public static bool Equals(DateOnly t1, DateOnly t2)
//        {
//            return t1.m_UnderlyingValue.Equals(t2.m_UnderlyingValue);
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="s"></param>
//        /// <param name="result"></param>
//        /// <returns></returns>
//        public static bool TryParse(string s, out DateOnly result)
//        {
//            DateTime t1;
//            var canParse = DateTime.TryParse(s, out t1);
//            if (canParse)
//                result = new DateOnly(t1);
//            else
//                result = new DateOnly();
//            return canParse;
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="s"></param>
//        /// <param name="provider"></param>
//        /// <param name="styles"></param>
//        /// <param name="result"></param>
//        /// <returns></returns>
//        public static bool TryParse(string s, IFormatProvider provider, DateTimeStyles styles, out DateOnly result)
//        {
//            DateTime t1;
//            var canParse = DateTime.TryParse(s, provider, styles, out t1);
//            if (canParse)
//                result = new DateOnly(t1);
//            else
//                result = new DateOnly();
//            return canParse;
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="s"></param>
//        /// <param name="format"></param>
//        /// <param name="provider"></param>
//        /// <param name="style"></param>
//        /// <param name="result"></param>
//        /// <returns></returns>
//        public static bool TryParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateOnly result)
//        {
//            DateTime t1;
//            var canParse = DateTime.TryParseExact(s, format, provider, style, out t1);
//            if (canParse)
//                result = new DateOnly(t1);
//            else
//                result = new DateOnly();
//            return canParse;
//        }
//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="s"></param>
//        /// <param name="formats"></param>
//        /// <param name="provider"></param>
//        /// <param name="style"></param>
//        /// <param name="result"></param>
//        /// <returns></returns>
//        public static bool TryParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateOnly result)
//        {
//            DateTime t1;
//            var canParse = DateTime.TryParseExact(s, formats, provider, style, out t1);
//            if (canParse)
//                result = new DateOnly(t1);
//            else
//                result = new DateOnly();
//            return canParse;
//        }

//        /// <summary>
//        /// Serves as a hash function for a particular type. 
//        /// </summary>
//        /// <returns>
//        /// A hash code for the current <see cref="T:System.Object" />.
//        /// </returns>
//        /// <filterpriority>2</filterpriority>
//        public override int GetHashCode()
//        {
//            return m_UnderlyingValue.GetHashCode();
//        }


//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="kind"></param>
//        /// <returns></returns>
//        public DateTime ToDateTime(DateTimeKind kind)
//        {
//            return new DateTime(m_UnderlyingValue.Year, m_UnderlyingValue.Month, m_UnderlyingValue.Day, 0, 0, 0, kind);
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <returns></returns>
//        public DateTime ToLocalTime()
//        {
//            return ToDateTime(DateTimeKind.Local);
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <returns></returns>
//        public DateTime ToUniversalTime()
//        {
//            return m_UnderlyingValue;
//        }


//        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode"), SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
//        [ContractInvariantMethod]
//        void ObjectInvariant()
//        {
//            Contract.Invariant(m_UnderlyingValue.Hour == 0);
//            Contract.Invariant(m_UnderlyingValue.Minute == 0);
//            Contract.Invariant(m_UnderlyingValue.Second == 0);
//        }

//    }
//}



